﻿using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Collections.Generic;
using PlayDeezGames.Common;

namespace ASCII.Common
{
    public class ASCIIRenderer
    {
        private Board<ASCIICell> board;
        public Board<ASCIICell> Board
        {
            get
            {
                return board;
            }
        }
        private ImageBrushes brushes = new ImageBrushes();
        private GridBoard gridBoard;
        public GridBoard GridBoard
        {
            get
            {
                return gridBoard;
            }
            set
            {
                gridBoard = value;
                board = new Board<ASCIICell>(gridBoard.Columns, gridBoard.Rows);
            }
        }
        public ASCIIRenderer()
        {
            foreach (ASCIICellColor theColor in new ASCIICellColor[] { ASCIICellColor.Black, ASCIICellColor.DarkBlue, ASCIICellColor.DarkGreen, ASCIICellColor.DarkCyan, ASCIICellColor.DarkRed, ASCIICellColor.DarkMagenta, ASCIICellColor.DarkYellow, ASCIICellColor.Gray, ASCIICellColor.DarkGray, ASCIICellColor.Blue, ASCIICellColor.Green, ASCIICellColor.Cyan, ASCIICellColor.Red, ASCIICellColor.Magenta, ASCIICellColor.Yellow, ASCIICellColor.White })
            {
                for (int theCharacter = byte.MinValue; theCharacter <= byte.MaxValue; ++theCharacter)
                {
                    brushes.LookUpTable.Add(string.Format("{1}_{0}", theCharacter, (int)theColor), string.Format("/ASCII.Common;component/images/{1}_{0}.png", theCharacter, (int)theColor));
                }
            }
        }
        public byte GetCellCharacter(int column, int row)
        {
            return Board[column][row].Character;
        }
        public ASCIICellColor GetCellForegroundColor(int column, int row)
        {
            return Board[column][row].ForegroundColor;

        }
        public ASCIICellColor GetCellBackgroundColor(int column, int row)
        {
            return Board[column][row].BackgroundColor;
        }
        public void SetCellCharacter(int column, int row, byte theCharacter)
        {
            Board[column][row].Character = theCharacter;
        }
        public void SetCellForegroundColor(int column, int row, ASCIICellColor theColor)
        {
            Board[column][row].ForegroundColor = theColor;
        }
        public void SetCellBackgroundColor(int column, int row, ASCIICellColor theColor)
        {
            Board[column][row].BackgroundColor = theColor;
        }
        public void SetCells(int left, int top, int width, int height, byte theCharacter, bool setCharacter, ASCIICellColor theForegroundColor, bool setForeground, ASCIICellColor theBackgroundColor, bool setBackground)
        {
            for (int column = left; column < left + width; ++column)
            {
                if (column >= 0 && column < GridBoard.Columns)
                {
                    for (int row = top; row < top + height; ++row)
                    {
                        if (row >= 0 && row < GridBoard.Rows)
                        {
                            if (setCharacter)
                            {
                                SetCellCharacter(column, row, theCharacter);
                            }
                            if (setForeground)
                            {
                                SetCellForegroundColor(column, row, theForegroundColor);
                            }
                            if (setBackground)
                            {
                                SetCellBackgroundColor(column, row, theBackgroundColor);
                            }
                        }
                    }
                }
            }
        }
        public void SetCells(int left, int top, int width, int height, byte theCharacter)
        {
            SetCells(left, top, width, height, theCharacter, true, ASCIICellColor.Black, false, ASCIICellColor.Black, false);
        }
        public void SetCells(int left, int top, int width, int height, byte theCharacter, ASCIICellColor theForegroundColor)
        {
            SetCells(left, top, width, height, theCharacter, true, theForegroundColor, true, ASCIICellColor.Black, false);
        }
        public void SetCells(int left, int top, int width, int height, byte theCharacter, ASCIICellColor theForegroundColor, ASCIICellColor theBackgroundColor)
        {
            SetCells(left, top, width, height, theCharacter, true, theForegroundColor, true, theBackgroundColor, true);
        }

        public void SetCell(int column, int row, byte theCharacter, bool setCharacter, ASCIICellColor theForegroundColor, bool setForeground, ASCIICellColor theBackgroundColor, bool setBackground)
        {
            SetCells(column, row, 1, 1, theCharacter, setCharacter, theForegroundColor, setForeground, theBackgroundColor, setBackground);
        }
        public void SetCell(int column, int row, byte theCharacter)
        {
            SetCell(column, row, theCharacter, true, ASCIICellColor.Black, false, ASCIICellColor.Black, false);
        }
        public void SetCell(int column, int row, byte theCharacter, ASCIICellColor theForegroundColor)
        {
            SetCell(column, row, theCharacter, true, theForegroundColor, true, ASCIICellColor.Black, false);
        }
        public void SetCell(int column, int row, byte theCharacter, ASCIICellColor theForegroundColor, ASCIICellColor theBackgroundColor)
        {
            SetCell(column, row, theCharacter, true, theForegroundColor, true, theBackgroundColor, true);
        }

        public void WriteText(int left, int top, string theString, ASCIICellColor theForegroundColor, ASCIICellColor theBackgroundColor)
        {
            if (top >= 0 && top < GridBoard.Rows)
            {
                foreach (char character in theString)
                {
                    if (left >= 0 && left < GridBoard.Columns)
                    {
                        SetCell(left, top, (byte)character, theForegroundColor, theBackgroundColor);
                    }
                    left++;
                }
            }
        }

        public void Render(int left, int top, int width, int height)
        {
            int right = left + width;
            int bottom = top + height;
            if (left < 0) left = 0;
            if (top < 0) top = 0;
            if (right > gridBoard.Columns) right = gridBoard.Columns;
            if (bottom > gridBoard.Rows) bottom = gridBoard.Rows;
            for (int column = left; column < right; ++column)
            {
                for (int row = top; row < bottom; ++row)
                {
                    if (Board[column][row].Dirty)
                    {
                        Board[column][row].Dirty = false;
                        ImageBrush backBrush = brushes[string.Format("{0}_219", (int)GetCellBackgroundColor(column, row))];
                        ImageBrush foreBrush = brushes[string.Format("{1}_{0}", GetCellCharacter(column, row), (int)GetCellForegroundColor(column, row))];
                        if (GridBoard[column][row][0].Fill != backBrush)
                        {
                            GridBoard[column][row][0].Fill = backBrush;
                        }
                        else
                        {
                        }
                        if (GridBoard[column][row][1].Fill != foreBrush)
                        {
                            GridBoard[column][row][1].Fill = foreBrush;
                        }
                        else
                        {
                        }
                    }
                }
            }
        }
        public void Render()
        {
            Render(0, 0, GridBoard.Columns, GridBoard.Rows);
        }
        public void DrawTable(TableDrawingPalette palette, int[] columns, int[] rows,ASCIICellColor foreground,ASCIICellColor background,bool DrawBlanks)
        {
            for (int column = columns[0]; column <= columns[columns.Length - 1]; ++column)
            {
                for (int row = rows[0]; row <= rows[rows.Length - 1]; ++row)
                {
                    int verticalDividerIndex = -1;
                    int horizontalDividerIndex = -1;
                    int dividerIndex;
                    for (dividerIndex = 0; dividerIndex < columns.Length; ++dividerIndex)
                    {
                        if (column == columns[dividerIndex])
                        {
                            verticalDividerIndex = dividerIndex;
                            break;
                        }
                    }
                    for (dividerIndex = 0; dividerIndex < rows.Length; ++dividerIndex)
                    {
                        if (row == rows[dividerIndex])
                        {
                            horizontalDividerIndex = dividerIndex;
                            break;
                        }
                    }
                    byte theCharacter = palette[TableDrawingPaletteEntry.Blank];
                    if (verticalDividerIndex != -1 && horizontalDividerIndex != -1)
                    {
                        if (verticalDividerIndex == 0)
                        {
                            if (horizontalDividerIndex == 0)
                            {
                                //top left
                                theCharacter = palette[TableDrawingPaletteEntry.TopLeft];
                            }
                            else if (horizontalDividerIndex == rows.Length - 1)
                            {
                                //bottom left
                                theCharacter = palette[TableDrawingPaletteEntry.BottomLeft];
                            }
                            else
                            {
                                //left tee
                                theCharacter = palette[TableDrawingPaletteEntry.LeftTee];
                            }
                        }
                        else if (verticalDividerIndex == columns.Length - 1)
                        {
                            if (horizontalDividerIndex == 0)
                            {
                                //top right
                                theCharacter = palette[TableDrawingPaletteEntry.TopRight];
                            }
                            else if (horizontalDividerIndex == rows.Length - 1)
                            {
                                //bottom right
                                theCharacter = palette[TableDrawingPaletteEntry.BottomRight];
                            }
                            else
                            {
                                //right tee
                                theCharacter = palette[TableDrawingPaletteEntry.RightTee];
                            }
                        }
                        else
                        {
                            if (horizontalDividerIndex == 0)
                            {
                                //top tee
                                theCharacter = palette[TableDrawingPaletteEntry.TopTee];
                            }
                            else if (horizontalDividerIndex == rows.Length - 1)
                            {
                                //bottom tee
                                theCharacter = palette[TableDrawingPaletteEntry.BottomTee];
                            }
                            else
                            {
                                //cross
                                theCharacter = palette[TableDrawingPaletteEntry.Cross];
                            }
                        }
                    }
                    else if (verticalDividerIndex != -1)
                    {
                        //vertical
                        theCharacter = palette[TableDrawingPaletteEntry.Vertical];
                    }
                    else if (horizontalDividerIndex != -1)
                    {
                        //horizontal
                        theCharacter = palette[TableDrawingPaletteEntry.Horizontal];
                    }
                    else
                    {
                        if (!DrawBlanks) continue;
                    }
                    SetCell(column, row, theCharacter, foreground, background);
                }
            }
        }
        public int GetMouseColumn(UIElement relativeTo,MouseEventArgs e)
        {
            double x = e.GetPosition(relativeTo).X;
            x /= GridBoard.Width;
            x *= GridBoard.Columns;
            return (int)x;
        }
        public int GetMouseRow(UIElement relativeTo, MouseEventArgs e)
        {
            double y = e.GetPosition(relativeTo).Y;
            y /= GridBoard.Height;
            y *= GridBoard.Rows;
            return (int)y;
        }
        public bool MouseInButton(int x, int y, string text,UIElement relativeTo,MouseEventArgs e)
        {
            int column = GetMouseColumn(relativeTo, e);
            int row = GetMouseRow(relativeTo, e);
            return ((column >= x) && (row >= y) && (column < x + 2 + text.Length) && (row < y + 3));
        }
        public void DrawButton(int x, int y, string text, bool pressed, bool hover, bool focus, bool enabled)
        {
            TableDrawingPalette palette = null;
            ASCIICellColor backgroundColor = ASCIICellColor.Black;
            ASCIICellColor textColor;
            ASCIICellColor borderColor;
            if (focus)
            {
                palette = TableDrawingPalette.V2H2Palette;
            }
            else
            {
                palette = TableDrawingPalette.V1H1Palette;
            }
            if (enabled)
            {
                if (hover)
                {
                    if (pressed)
                    {
                        borderColor = ASCIICellColor.Green;
                        textColor = ASCIICellColor.White;
                    }
                    else
                    {
                        borderColor = ASCIICellColor.Yellow;
                        textColor = ASCIICellColor.White;
                    }
                }
                else
                {
                    borderColor = ASCIICellColor.Blue;
                    textColor = ASCIICellColor.Gray;
                }
            }
            else
            {
                textColor = ASCIICellColor.DarkGray;
                borderColor = ASCIICellColor.DarkGray;
            }
            DrawTable(palette, new int[] {x,x+2+text.Length-1 }, new int[] {y,y+2 }, borderColor, backgroundColor, true);
            WriteText(x + 1, y + 1, text, textColor, backgroundColor);
        }


    }
}
